// 实现这个项目的构建任务
const { src, dest, parallel, series, watch } = require('gulp')

const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
const sass = require('gulp-sass')(require('node-sass'))

const path = require('path')
const del = require('del')
const browserSync = require('browser-sync')
const bs = browserSync.create()
const cwd = process.cwd()
let config = {
  // default
  build: {
    src: 'src',
    dist: 'dist',
    temp: 'temp',
    public: 'public',
    paths: {
        styles: 'assets/styles/*.scss',
        scripts: 'assets/scripts/*.js',
        pages: '*.html',
        images: 'assets/images/**',
        fonts: 'assets/fonts/**'
    }
  }
}

try {
  let loadConfig = require(path.join(cwd, 'pages.config.js'))
  config = Object.assign({}, config, loadConfig)
} catch (e) {}

const clean = () => {
    return del([config.build.dist, config.build.temp])
}

const style = () => {
    return src(config.build.paths.styles, { base: config.build.src, cwd: config.build.src })    // cwd是指 路径要从cwd下面去找
    .pipe(sass({ outputStyle: 'expanded'}))
    .pipe(dest(config.build.temp))
    .pipe(bs.reload({ stream: true}))
}

const script = () => {
    return src(config.build.paths.scripts, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.babel({ presets: [require('@babel/preset-env')] }))   // presets是在node_modules根目录找 @babel/preset-env  使用require,就是往上依次找
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true}))
}

const page = () => {
    return src(config.build.paths.pages, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.swig({ data: config.data, defaults: { cache: false }}))   // 防止模板缓存导致页面不能及时更新
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true}))
}

const image = () => {
    return src(config.build.paths.images, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.imagemin())
        .pipe(dest(config.build.dist))
}

const font = () => {
    return src(config.build.paths.fonts, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.imagemin())
        .pipe(dest(config.build.dist))
}

const extra = () => {
    return src('**', { base: config.build.public, cwd: config.build.public })
        .pipe(dest(config.build.dist))
}


const serve = () => {
    // 在服务器运行阶段，监听指定目录下文件发生改变时，然后执行对应的任务
    watch(config.build.paths.styles, { cwd: config.build.src }, style)
    watch(config.build.paths.scripts, { cwd: config.build.src }, script)
    watch(config.build.paths.pages, { cwd: config.build.src }, page)
    // watch('src/assets/images/**', image)
    // watch('src/assets/fonts/**', font)
    // watch('public/**', extra)
    watch([
        config.build.paths.images,
        config.build.paths.fonts,
    ], { cwd: config.build.src }, bs.reload)
    
    watch('**', { cwd: config.build.public }, bs.reload)

    // 初始化启动web服务的配置
    bs.init({
        notify: false,  // 浏览器右上角的提示
        port: 2080,
        // open: false, // 是否自动打开浏览器
        // files: 'dist/**',  //指定位置文件发生改变时，刷新浏览器   可以使用bs.reload代替
        server: {
            // 指定根目录 项目中的请求路径会依次寻找
            baseDir: [config.build.temp, config.build.src, config.build.public] ,
            // 路由映射 优先级高于baseDir
            routes: {
                '/node_modules': 'node_modules'
            }
        }
    })
}

const useref = () => {
    return src(config.build.paths.pages, { base: config.build.temp, cwd: config.build.temp})
        .pipe(plugins.useref({ searchPath: [config.build.temp, '.']}))     //指定构建注释里面的引入文件的引用请求的查找路径 依次寻找
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({ 
            collapseWhitespace: true, 
            minifyCSS: true,
            minifyJS: true,
        })))
        .pipe(dest(config.build.dist))
}

const compile = parallel(style, script, page)

const build = series(
    clean,
    parallel(
        series(compile, useref),
        image,
        font,
        extra
    )
)

const develop = series(compile, serve)

module.exports = {
    clean,
    develop,
    build,
}